{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一、python语法基础\n",
    "接下来我们来夯实基础，我们会不断review这个章节，逐渐掌握python语言的技术细节\n",
    "![](images/python.jpg?20170615)\n",
    "### 1. 标准输出和输入\n",
    "标准输出，默认情况下向屏幕设备输出，也可以向文件和网络设备输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world!\n",
      "Hello world !\n"
     ]
    }
   ],
   "source": [
    "print('Hello world!')\n",
    "print('Hello', 'world', '!') #自动添加空格"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Please input: Hello\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Hello'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#words = raw_input('Please input: ') #python 2中使用raw_input函数返回字符串，input返回数字.通过命令行执行\n",
    "#words = raw_input('请输入：'.decode('utf-8').encode('GB2312')) #执行python代码文件时，这里的中文会出现乱码，python 2需要特别注意乱码的问题\n",
    "words = input('Please input: ')\n",
    "words"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 基本数据类型\n",
    "\n",
    "计算机底层使用的是二进制数据，为方便编程，各类语言都对二进制数据进行各种抽象，进而提供基本数据类型和用户自定义类型\n",
    "- 整数（int）：python 2中有长整型long，python3统一为int\n",
    "- 浮点数（float）\n",
    "- 复数（complex）\n",
    "- 字符串（str）\n",
    "- 布尔值（bool）\n",
    "- 元组（tuple）\n",
    "- 集合（set）\n",
    "- 列表（list）\n",
    "- 字典（dict）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 整数（int）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 8 16\n",
      "0b1010 0o12 0xa\n"
     ]
    }
   ],
   "source": [
    "a = 10\n",
    "b = 0b10 #二进制\n",
    "c = 0o10 #八进制\n",
    "d = 0x10 #十六进制\n",
    "print(b, c, d)\n",
    "print(bin(10), oct(10), hex(10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 浮点数（float）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.2 0.012 120.0\n"
     ]
    }
   ],
   "source": [
    "a = 1.2\n",
    "b = 1.2e-2\n",
    "c = 1.2e2\n",
    "print(a, b, c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 复数（complex）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1+2j) (3+4j) (4+6j)\n"
     ]
    }
   ],
   "source": [
    "a = complex(1,2)\n",
    "b = 3 + 4j\n",
    "c = a + b\n",
    "print(a, b, c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 字符串（str）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "It's time It\"s time It's time\n",
      "It's \n",
      "time\n",
      "It\\'s time\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"It's \\ntime\""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 'It\\'s time' #字符转义\n",
    "b = 'It\"s time'\n",
    "c = '''It's time''' \n",
    "d = \"\"\"It's \n",
    "time\"\"\" #支持多行文本\n",
    "e = r'It\\'s time'\n",
    "print(a, b, c)\n",
    "print(d)\n",
    "print(e)\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 布尔值（bool）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False True False True\n"
     ]
    }
   ],
   "source": [
    "a = True and False\n",
    "b = True or False\n",
    "c = not True\n",
    "d = 2 < 3\n",
    "print(a, b, c, d)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 数字"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 使用标准库中的数学函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "int(\"10\") =  10\n",
      "float(10) =  10.0\n",
      "complex(1,10) =  (1+10j)\n",
      "str(10) =  10\n",
      "chr(97) =  a\n",
      "ord(\"a\") =  97\n",
      "bin(10) =  0b1010\n",
      "oct(10) =  0o12\n",
      "hex(10) =  0xa\n",
      "--------------------\n",
      "abs(-1) =  1\n",
      "ceil(1.1) =  2\n",
      "floor(1.9) =  1\n",
      "max(1,2,3,4) =  4\n",
      "min(1,2,3,4) =  1\n",
      "modf(math.pi) =  (0.14159265358979312, 3.0)\n",
      "pow(2,3) 8.0\n",
      "round(1.4) 1\n",
      "round(1.5) 2\n",
      "sqrt(3) 1.7320508075688772\n",
      "operator.eq(1,2) =  False\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "import operator\n",
    "print('int(\"10\") = ', int(\"10\"))\n",
    "print('float(10) = ', float(10))\n",
    "print('complex(1,10) = ', complex(1,10))\n",
    "print('str(10) = ', str(10))\n",
    "print('chr(97) = ', chr(97))\n",
    "print('ord(\"a\") = ', ord(\"a\"))\n",
    "print('bin(10) = ', bin(10))\n",
    "print('oct(10) = ', oct(10))\n",
    "print('hex(10) = ', hex(10))\n",
    "print('-' * 20)\n",
    "print('abs(-1) = ', abs(-1))\n",
    "print('ceil(1.1) = ', math.ceil(1.1))\n",
    "print('floor(1.9) = ', math.floor(1.9))\n",
    "print('max(1,2,3,4) = ', max(1,2,3,4))\n",
    "print('min(1,2,3,4) = ', min(1,2,3,4))\n",
    "print('modf(math.pi) = ', math.modf(math.pi))\n",
    "print('pow(2,3)', math.pow(2,3))\n",
    "print('round(1.4)', round(1.4))\n",
    "print('round(1.5)', round(1.5))\n",
    "print('sqrt(3)', math.sqrt(3))\n",
    "print('operator.eq(1,2) = ',operator.eq(1,2))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "?math.ceil"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习：猜数字\n",
    "先提前掌握下面的条件判断语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "if True:\n",
    "    pass\n",
    "elif False:\n",
    "    pass\n",
    "else:\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type in a number:99\n",
      "It is too small.\n"
     ]
    }
   ],
   "source": [
    "n = input('Type in a number:')\n",
    "n = int(n)\n",
    "x = 120\n",
    "if n < x:\n",
    "    print('It is too small.')\n",
    "elif n > x:\n",
    "    print('It is too big.')\n",
    "else:\n",
    "    print('You are right.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 元组和列表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "先提前掌握下面的for循环语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(3):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 元组\n",
    "元组是一种序列，并且经过初始化就不能被修改，是不可变类型，另外不可变类型还包括字符串和数字"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": true
    },
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "t1 = (1,2)\n",
    "print('t1 = ',  t1)\n",
    "t2 = (3,) #如果只有一个元素，那么,是必须的，否则结果是数字3，而不是元组\n",
    "print('t2 = ',  t2)\n",
    "t3 = ()\n",
    "print('t3 = ',  t3)\n",
    "\n",
    "t4 = t1 + t2 + t3\n",
    "print('t4 = ', t4)\n",
    "t5 = t1 * 2\n",
    "print('t5 = ',  t5)\n",
    "print('t4[2] = ', t4[2])\n",
    "print('3 in t4 =' ,3 in t4)\n",
    "\n",
    "for i in t4:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 列表\n",
    "列表是另一种序列，其元素可以被修改\n",
    "![](images/list.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "l1 =  ['Mike', 'Jim', 'Brad']\n",
      "l2 =  ['Julia']\n",
      "l3 =  []\n",
      "l4 =  ['Mike', 'Jim', 'Brad', 'Julia']\n",
      "l5 =  ['Mike', 'Jim', 'Brad', 'Mike', 'Jim', 'Brad']\n",
      "l4.append('Hellen') then l4 =  ['Mike', 'Jim', 'Brad', 'Julia', 'Hellen']\n",
      "l4.insert(0, 'Bob') then l4 =  ['Bob', 'Mike', 'Jim', 'Brad', 'Julia', 'Hellen']\n",
      "Hellen\n",
      "l4.pop() then l4 =  ['Bob', 'Mike', 'Jim', 'Brad', 'Julia']\n",
      "l4.sort() then l4 =  ['Bob', 'Brad', 'Jim', 'Julia', 'Mike']\n",
      "l4.reverse() then l4 =  ['Mike', 'Julia', 'Jim', 'Brad', 'Bob']\n",
      "l4.extend(l2) then l4 =  ['Mike', 'Julia', 'Jim', 'Brad', 'Bob', 'Julia']\n",
      "l4.remove('Julia') then l4 =  ['Mike', 'Jim', 'Brad', 'Bob', 'Julia']\n",
      "del l4[0] then l4 =  ['Jim', 'Brad', 'Bob', 'Julia']\n",
      "['Mike', 'Jim', 'Brad', ['Java', 'Python'], 100, 200]\n",
      "Python\n",
      "Mike\n",
      "Jim\n",
      "Brad\n",
      "['Java', 'Python']\n",
      "100\n",
      "200\n"
     ]
    }
   ],
   "source": [
    "l1 = ['Mike', 'Jim', 'Brad']\n",
    "\n",
    "print('l1 = ', l1)\n",
    "l2 = ['Julia',]\n",
    "print('l2 = ', l2)\n",
    "l3 = []\n",
    "print('l3 = ', l3)\n",
    "\n",
    "l4 = l1 + l2 + l3\n",
    "print('l4 = ', l4)\n",
    "\n",
    "l5 = l1 * 2\n",
    "print('l5 = ', l5)\n",
    "\n",
    "l4.append('Hellen')\n",
    "print(\"l4.append('Hellen') then l4 = \", l4)\n",
    "l4.insert(0, 'Bob')\n",
    "print(\"l4.insert(0, 'Bob') then l4 = \", l4)\n",
    "print(l4.pop())\n",
    "print(\"l4.pop() then l4 = \",l4)\n",
    "l4.sort()\n",
    "print(\"l4.sort() then l4 = \",l4)\n",
    "l4.reverse()\n",
    "print(\"l4.reverse() then l4 = \",l4)\n",
    "l4.extend(l2)\n",
    "print(\"l4.extend(l2) then l4 = \",l4)\n",
    "l4.remove('Julia')\n",
    "print(\"l4.remove('Julia') then l4 = \",l4)\n",
    "del l4[0]\n",
    "print(\"del l4[0] then l4 = \",l4)\n",
    "\n",
    "\n",
    "l6 = ['Mike', 'Jim', 'Brad', ['Java', 'Python'], 100, 200]\n",
    "print(l6)\n",
    "print(l6[-3][1])\n",
    "\n",
    "\n",
    "for i in l6:\n",
    "    print(i)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 分片\n",
    "所有序列都可以分片，包括元组、列表、字典和集合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]\n",
      "[0, 2, 4, 6, 8]\n",
      "[10, 11, 12, 13, 14, 15, 16, 17, 18]\n",
      "[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]\n",
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 200, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]\n",
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]\n"
     ]
    }
   ],
   "source": [
    "li = list(range(20))\n",
    "\n",
    "print(li)\n",
    "print(li[0:10:2])\n",
    "print(li[-10:-1])\n",
    "print(li[-1::-1])\n",
    "print(li[:10])\n",
    "\n",
    "li[10:10] = [100,200]\n",
    "print(li)\n",
    "del li[10:12]\n",
    "print(li)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习：把小写字母列表转换为大写字母列表后，间隔一个字母选取子集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Q', 'E', 'T', 'U', 'O', 'A', 'D', 'G', 'J', 'L', 'X', 'V', 'N']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "letters = list('qwertyuiopasdfghjklzxcvbnm')\n",
    "\n",
    "up_letters = []\n",
    "for i in letters:\n",
    "    up_letters.append(i.upper())\n",
    "    \n",
    "up_letters[::2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. 字典和集合\n",
    "![](images/dict.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 字典\n",
    "字典是键值方式（key-value）存储的序列，在一个字典中key是唯一的，必须是不可变数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "d1 =  {'Mike': 100, 'Jim': 99, 'Brad': 98}\n",
      "d1[\"Mike\"] =  100\n",
      "d1[\"Mike\"] = 0 then d1[\"Mike\"] =  0\n",
      "d1.get(\"Hellen\") =  None\n",
      "d1.items() =  dict_items([('Mike', 0), ('Jim', 99), ('Brad', 98)])\n",
      "d1.keys() =  dict_keys(['Mike', 'Jim', 'Brad'])\n",
      "\"Hellen\" in d1 =  False\n",
      "d1.pop(\"Mike\") and d1.popitem() then d1 =  {'Jim': 99}\n",
      "d1[\"Hellen\"] = [99, 100] then d1 =  {'Jim': 99, 'Hellen': [99, 100]}\n",
      "d2 = d1.copy() then d2 =  {'Jim': 99, 'Hellen': [99, 100]}\n",
      "d2[\"Hellen\"].append(101) then d1 =  {'Jim': 99, 'Hellen': [99, 100, 101]}\n",
      "d3 = copy.deepcopy(d1) then d3 =  {'Jim': 99, 'Hellen': [99, 100, 101]}\n",
      "d3[\"Hellen\"].append(102) then d1 =  {'Jim': 99, 'Hellen': [99, 100, 101]}\n",
      "d3 =  {'Jim': 99, 'Hellen': [99, 100, 101, 102]}\n",
      "99\n",
      "[99, 100, 101]\n",
      "del d1[\"Jim\"] then d1 =  {'Hellen': [99, 100, 101]}\n",
      "dl.clear() then d1 =  {}\n"
     ]
    }
   ],
   "source": [
    "import copy\n",
    "\n",
    "d1 = {'Mike': 100, 'Jim': 99, 'Brad': 98}\n",
    "print('d1 = ', d1)\n",
    "print('d1[\"Mike\"] = ', d1['Mike'])\n",
    "d1['Mike'] = 0\n",
    "\n",
    "print('d1[\"Mike\"] = 0 then d1[\"Mike\"] = ', d1['Mike'])\n",
    "print('d1.get(\"Hellen\") = ', d1.get('Hellen'))  #如果索引取值时，key不存在会抛出异常，但是用get方法会返回None\n",
    "\n",
    "print('d1.items() = ', d1.items())\n",
    "print('d1.keys() = ', d1.keys())\n",
    "print('\"Hellen\" in d1 = ', \"Hellen\" in d1)\n",
    "d1.pop(\"Mike\")\n",
    "d1.popitem()\n",
    "print('d1.pop(\"Mike\") and d1.popitem() then d1 = ', d1)\n",
    "\n",
    "d1['Hellen'] = [99, 100]\n",
    "\n",
    "print('d1[\"Hellen\"] = [99, 100] then d1 = ', d1)\n",
    "d2 = d1.copy()\n",
    "print('d2 = d1.copy() then d2 = ',d2)\n",
    "d2['Hellen'].append(101)\n",
    "\n",
    "print('d2[\"Hellen\"].append(101) then d1 = ' , d1)\n",
    "\n",
    "d3 = copy.deepcopy(d1)\n",
    "print('d3 = copy.deepcopy(d1) then d3 = ', d3)\n",
    "d3['Hellen'].append(102)\n",
    "print('d3[\"Hellen\"].append(102) then d1 = ', d1)\n",
    "print('d3 = ', d3)\n",
    "\n",
    "for i in d1:\n",
    "    print(d1[i])\n",
    "\n",
    "del d1[\"Jim\"]\n",
    "print('del d1[\"Jim\"] then d1 = ', d1)\n",
    "d1.clear()\n",
    "\n",
    "print('dl.clear() then d1 = ', d1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 集合\n",
    "集合可以看作是只有key而没有value的字典，因而集合中的元素是唯一的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Jim', 'Mike', 'Brad'}\n",
      "{1, 2, 3}\n",
      "{1, 2, 3}\n",
      "{2, 3}\n"
     ]
    }
   ],
   "source": [
    "s1 = {'Mike', 'Jim', 'Brad'}\n",
    "print(s1)\n",
    "s2 = set([1, 2, 3, 1, 2])\n",
    "print(s2)\n",
    "s2.add(1)\n",
    "print(s2)\n",
    "s2.remove(1)\n",
    "print(s2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习：从价格字典中提取价格大于200的子集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "prices = {'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'AAPL': 612.78, 'IBM': 205.55}"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p1 = {}\n",
    "for key, val in prices.items():\n",
    "    if val > 200:\n",
    "        p1[key] = val\n",
    "p1\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. 变量赋值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3\n",
      "2 1 3\n",
      "4 5 6\n",
      "1 2 [3, 4]\n"
     ]
    }
   ],
   "source": [
    "a, b, c = 1, 2, 3\n",
    "print(a, b, c)\n",
    "a, b = b, a\n",
    "\n",
    "print(a, b, c)\n",
    "x = 4, 5, 6 #自动打包\n",
    "a, b, c = x #自动解包\n",
    "print(a, b, c)\n",
    "a, b, *c = 1, 2, 3, 4\n",
    "print(a, b, c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习：感受python的赋值魔法，冒泡排序算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[99, 56, 14, 0, 11, 74, 4, 85, 88, 10, 12, 98, 45, 30, 2, 3, 100, 2, 44, 82]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import random\n",
    "random.seed(1234)\n",
    "number_list = [random.randint(0, 100) for _ in range(20)]\n",
    "number_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 2, 3, 4, 10, 11, 12, 14, 30, 44, 45, 56, 74, 82, 85, 88, 98, 99, 100]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n = len(number_list)\n",
    "for j in range(n):\n",
    "    for i in range(n - 1 - j):        \n",
    "        if number_list[i] > number_list[i + 1]:\n",
    "            number_list[i], number_list[i + 1] = number_list[i + 1], number_list[i]\n",
    "number_list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. 运算符\n",
    "- 算术：+  -  \\*  /  %  \\*\\*  //\n",
    "- 比较：==  !=   <>  >  <  >=  <=\n",
    "- 赋值：=  +=  -=  \\*=  /=  %=  \\*\\*=  //=\n",
    "- 逻辑：and   or   not\n",
    "- 位：&  |  ^  ~  <<  >>\n",
    "- 其他：in  not in  is  is not"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a + b =  7\n",
      "a - b =  3\n",
      "a * b =  10\n",
      "a / b =  2.5\n",
      "a % b =  1\n",
      "a ** b =  25\n",
      "a // b =  2\n",
      "--------------------\n",
      "a > b =  True\n",
      "a < b =  False\n",
      "a != b =  True\n",
      "a >= b =  True\n",
      "a <= b =  False\n",
      "--------------------\n",
      "a += b then a =  7\n",
      "a -= b then a =  5\n",
      "a *= b then a =  10\n",
      "a /= b then a =  5.0\n",
      "a %= b then a =  1.0\n",
      "a **= b then a =  1.0\n",
      "a //= b then a =  0.0\n",
      "--------------------\n",
      "a & b =  0\n",
      "a | b =  7\n",
      "a ^ b =  7\n",
      "~a =  -6\n",
      "a << 2 =  20\n",
      "a >> 2 =  1\n"
     ]
    }
   ],
   "source": [
    "a = 5\n",
    "b = 2\n",
    "print(\"a + b = \", a + b)\n",
    "print(\"a - b = \", a - b)\n",
    "print(\"a * b = \", a * b)\n",
    "print(\"a / b = \", a / b)\n",
    "print(\"a % b = \", a % b)\n",
    "print(\"a ** b = \", a ** b)\n",
    "print(\"a // b = \", a // b)\n",
    "\n",
    "print(\"-\" * 20)\n",
    "print(\"a > b = \", a > b) \n",
    "print(\"a < b = \", a < b)\n",
    "print(\"a != b = \", a != b) \n",
    "print(\"a >= b = \", a >= b) \n",
    "print(\"a <= b = \", a <= b)\n",
    "\n",
    "print(\"-\" * 20)\n",
    "a += b\n",
    "print(\"a += b then a = \", a)\n",
    "a -= b\n",
    "print(\"a -= b then a = \", a)\n",
    "a *= b\n",
    "print(\"a *= b then a = \", a)\n",
    "a /= b\n",
    "print(\"a /= b then a = \", a)\n",
    "a %= b\n",
    "print(\"a %= b then a = \", a)\n",
    "a **= b\n",
    "print(\"a **= b then a = \", a)\n",
    "a //= b\n",
    "print(\"a //= b then a = \", a)\n",
    "\n",
    "print(\"-\" * 20)\n",
    "a = 5  # 00000101\n",
    "b = 2  # 00000010\n",
    "print(\"a & b = \", a & b)\n",
    "print(\"a | b = \", a | b) \n",
    "print(\"a ^ b = \", a ^ b) \n",
    "c = ~a\n",
    "print(\"~a = \", c)\n",
    "c = a << 2\n",
    "print(\"a << 2 = \", c) # 00010100\n",
    "c = a >> 2\n",
    "print(\"a >> 2 = \", c) # 00000001"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. 控制语句"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习：改进猜数字游戏，允许猜测次数增加为2次，3次和无限次"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type in a number: 99\n",
      "You are right.\n",
      "Type in a number again: 100\n",
      "You are wrong.\n"
     ]
    }
   ],
   "source": [
    "n = input('Type in a number: ')\n",
    "n = int(n)\n",
    "x = 99\n",
    "\n",
    "if n < x:\n",
    "    print('It is too small.')\n",
    "elif n > x:\n",
    "    print('It is too big.')\n",
    "else:\n",
    "    print('You are right.')\n",
    "\n",
    "n = input('Type in a number again: ')\n",
    "n = int(n)\n",
    "if n < x or n > x:\n",
    "    print('You are wrong.')\n",
    "else:\n",
    "    print('You are right.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "给猜更多机会"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type in a number: 99\n",
      "You are right.\n"
     ]
    }
   ],
   "source": [
    "count = 4\n",
    "x = 99\n",
    "\n",
    "for i in range(count):\n",
    "    if i == 0:\n",
    "        continue\n",
    "    \n",
    "    n = input('Type in a number: ')\n",
    "    n = int(n)\n",
    "    c = count - i - 1\n",
    "    if n < x:\n",
    "        print('It is too small. %d chances left.' % c)\n",
    "    elif n > x:\n",
    "        print('It is too big. %d chances left.' % c)\n",
    "    else:\n",
    "        print('You are right.')\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "给猜无数次机会"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type in a number: 99\n",
      "You are right.\n"
     ]
    }
   ],
   "source": [
    "while True:\n",
    "    n = input('Type in a number: ')\n",
    "    n = int(n)\n",
    "    x = 99\n",
    "    \n",
    "    if n < x:\n",
    "        print('It is too small.')\n",
    "    elif n > x:\n",
    "        print('It is too big.')\n",
    "    else:\n",
    "        print('You are right.')\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 Donn\n",
      "2 Shirley\n",
      "3 Ben\n"
     ]
    }
   ],
   "source": [
    "names = ['Donn', 'Shirley', 'Ben']\n",
    "for i, name in enumerate(names): #enumerate内置函数还返回索引值\n",
    "    print (\"%d %s\" % (i + 1, name))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Donn\n",
      "Shirley\n",
      "Ben\n"
     ]
    }
   ],
   "source": [
    "names = ['Donn', 'Shirley', 'Ben']\n",
    "for i,name in enumerate(names):\n",
    "    print(name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 二、python语法进阶"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 使用random产生随机数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "choice(range(10)) =  9\n",
      "randrange(0,10,2) =  7\n",
      "random() =  0.6158156951036152\n",
      "uniform(10,20) =  11.485546387082875\n",
      "randomint(10) =  12\n",
      "shuffle([1,2,3,4]) then  [3, 2, 4, 1]\n",
      "random.sample(a, 2) =  [2, 3]\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "#random.seed(1234) #设置随机种子每次将产生相同的随机数\n",
    "print('choice(range(10)) = ', random.choice(range(10)))\n",
    "print('randrange(0,10,2) = ', random.randrange(0,10))\n",
    "print('random() = ', random.random())\n",
    "print('uniform(10,20) = ', random.uniform(10,20))\n",
    "print('randomint(10) = ', random.randint(10, 20))\n",
    "a = [1,2,3,4]\n",
    "random.shuffle(a)\n",
    "print('shuffle([1,2,3,4]) then ', a)\n",
    "print('random.sample(a, 2) = ', random.sample(a, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 列表推导式\n",
    "列表推导式是python的语法糖，用来快速生成列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "[0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0, 81.0]\n",
      "[25.0, 36.0, 49.0, 64.0, 81.0]\n",
      "--------------------\n",
      "[('Beer', 'Water'), ('Beer', 'Soda'), ('Beer', 'Juice'), ('Wine', 'Water'), ('Wine', 'Soda'), ('Wine', 'Juice')]\n",
      "[('Beer', 'Water'), ('Wine', 'Soda')]\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "series = range(10)\n",
    "print([item for item in series])\n",
    "print([math.pow(item, 2) for item in series])\n",
    "print([math.pow(item, 2) for item in series if item > 4])\n",
    "\n",
    "print('-' * 20)\n",
    "booze = ['Beer', 'Wine']\n",
    "soft_drinks = ['Water', 'Soda', 'Juice']\n",
    "print([(x, y) for x in booze for y in soft_drinks])\n",
    "print([x for x in zip(booze, soft_drinks)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "#### 练习1：列表推导式改进把小写字母列表转换为大写字母列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "letters = list('qwertyuiopasdfghjklzxcvbnm')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Q', 'E', 'T', 'U', 'O', 'A', 'D', 'G', 'J', 'L', 'X', 'V', 'N']"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "up_letters = [x.upper() for x in letters]\n",
    "up_letters[::2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习2：创建一个包含10个随机数的列表，选出其中偶数项，再选出偶数项中最大的2项"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[76, 86]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import random\n",
    "numbers = []\n",
    "for _ in range(10):\n",
    "    numbers.append(random.randint(0, 100))\n",
    "even_numbers= []\n",
    "for i in numbers:\n",
    "    if i % 2 == 0:\n",
    "        even_numbers.append(i)\n",
    "even_numbers.sort()\n",
    "even_numbers[-2:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[82, 38]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numbers = sorted([x for x in [random.randint(0, 100) for _ in range(10)] if x % 2 == 0], reverse = True)\n",
    "numbers[:2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 字典推导式和集合推导式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Mike': 'Python', 'Jim': 'Ruby', 'Brad': 'PHP'}\n",
      "{'Python': 'Mike', 'Ruby': 'Jim', 'PHP': 'Brad'}\n",
      "{'Beer': 'Water', 'Wine': 'Soda', 'Scotch': 'Juice'}\n",
      "{'y', 'P'}\n"
     ]
    }
   ],
   "source": [
    "list_of_tuples = [('Mike','Python'),('Jim','Ruby'),('Brad','PHP')]\n",
    "\n",
    "d1 = {key: value for key, value in list_of_tuples}\n",
    "print(d1)\n",
    "d2 = {val: key for key, val in d1.items()}\n",
    "print(d2)\n",
    "\n",
    "booze = ['Beer', 'Wine', 'Scotch']\n",
    "soft_drinks = ['Water', 'Soda', 'Juice']\n",
    "d3 = {key: val for key, val in zip(booze, soft_drinks) }\n",
    "print(d3)\n",
    "s1 = {key for key in 'Python' if key not in 'thon'}\n",
    "print(s1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习：使用字典推导式改进从价格字典中提取价格大于200的子集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "prices = {'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'AAPL': 612.78, 'IBM': 205.55}"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p1 = {key: val for key, val in prices.items() if val > 200}\n",
    "p1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 不可变类型和可变类型\n",
    "在python中数字、字符串、元组是不可变类型，列表、字典是可变类型。不可变类型的对象不能在内存中就地修改，python也没有提供修改的api，而可变类型的对象在内存中可以被就地修改。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 1506195952\n",
      "3 1506195984\n"
     ]
    }
   ],
   "source": [
    "i = 2 #创建int对象，值为2\n",
    "print(i, id(i))\n",
    "i = i + 1 #创建新的int对象，值为3，i指向新对象\n",
    "print(i, id(i))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "abc 2378731047880\n",
      "abd 2378769718216\n"
     ]
    }
   ],
   "source": [
    "s = 'abc' #创建str对象，值为abc\n",
    "print(s, id(s))\n",
    "s = s.replace('c', 'd') #replace方法创建新的str对象，值为abd，s指向新对象\n",
    "print(s, id(s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3] 2378769767432\n",
      "[1, 2, 3, 4] 2378769767432\n"
     ]
    }
   ],
   "source": [
    "li = [1, 2, 3] #创建list对象，值为[1, 2, 3]\n",
    "print(li, id(li))\n",
    "li.append(4) #append方法修改对象，值为[1, 2, 3，4]\n",
    "print(li, id(li))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但是，对于较小的int类型和较短的str类型，为节省内存空间，具有相同值的变量指向同一个对象，但是该对象依然是不可变的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 1506195952\n",
      "2 1506195952\n",
      "2000 2378770322928\n",
      "2000 2378770322448\n"
     ]
    }
   ],
   "source": [
    "i1 = 2\n",
    "print(i1, id(i1))\n",
    "i2 = 2\n",
    "print(i2, id(i2))\n",
    "i1 = 2000\n",
    "print(i1, id(i1))\n",
    "i2 = 2000\n",
    "print(i2, id(i2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三. 字符串和正则表达式基础"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "It's time It's time It's time\n",
      "It's \n",
      "time\n",
      "It's time\n",
      "It\\'s time\n",
      "[\\ \n",
      " ' \t \"]\n",
      "中文\n"
     ]
    }
   ],
   "source": [
    "a = 'It\\'s time' #转义字符\n",
    "b = \"It's time\"\n",
    "c = '''It's time''' \n",
    "d = \"\"\"It's \n",
    "time\"\"\" #支持多行文本\n",
    "e = \"It's \"\\\n",
    "\"time\" \n",
    "f = r'It\\'s time'\n",
    "g = \"\"\"[\\\\ \\n \\' \\t \\\"]\"\"\" #常用转义字符\n",
    "h = \"中文\"\n",
    "print(a, b, c)\n",
    "print(d)\n",
    "print(e)\n",
    "print(f)\n",
    "print(g)\n",
    "print(h)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 字符编码\n",
    "任何数据类型都是对底层二进制数据的抽象，计算机只能处理数字，如果要处理文本，就必须先把文本转换为数字才行\n",
    "\n",
    "计算机在设计时采用8个比特（bit）作为一个字节（byte），一个字节能表示的最大的整数范围是0-255（二进制00000000-11111111），如果要表示更大的整数，就必须用更多的字节。比如两个字节可以表示的最大整数是65535，4个字节可以表示的最大整数是4294967295\n",
    "\n",
    "计算机处理文本的方式，就是使用一个整数代表一个文本字符\n",
    "\n",
    "ASCII编码只有127个字符，使用1个字节，包括大小写英文字母、数字和一些符号。比如大写字母A的编码是65（二进制01000001），小写字母z的编码是122（二进制1111010）\n",
    "\n",
    "使用非英文字符的国家，ASCII编码难以满足要求，中国制定了GB2312编码，使用2个字节，对汉字进行编码\n",
    "\n",
    "但是不同国家不同标准，在多语言混合的文本中，就会出现乱码。Unicode编码把所有语言都统一到一套编码里，Unicode定义了字符与整数的对应关系，一般使用2个以上字节\n",
    "\n",
    "为节省空间，UTF-8编码把Unicode字符根据不同的数字大小编码成1-6个字节，英文字母被编码成1个字节，汉字一般是3个字节，生僻的字符被编码成4-6个字节"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. python 3中的字符编码\n",
    "python 3的重要改进是解决了python 2中的字符编码问题：\n",
    "- python 3默认编码是UTF-8编码，python 2是ASCII编码\n",
    "- python 3中字符串都是str类型，都是Unicode编码，python 2中字符串有unicode和str是两种类型，分别是Unicode编码和ASCII编码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "65 0b1000001 <class 'str'> b'A' 1\n",
      "27721 0b110110001001001 <class 'str'> b'\\xe6\\xb1\\x89' 3\n"
     ]
    }
   ],
   "source": [
    "a = 'A'\n",
    "b = '汉'\n",
    "print(ord(a), bin(ord(a)), type(a), a.encode('utf-8'), len(a.encode('utf-8')))\n",
    "print(ord(b), bin(ord(b)), type(a), b.encode('utf-8'), len(b.encode('utf-8')))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](images/python3encode.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在python代码文件中使用以下声明告知解释器使用utf-8的方式解码python代码文本\n",
    "#-\\*- coding: utf-8 -\\*-"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'utf-8'"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "sys.getdefaultencoding()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 使用标准库中的字符串函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "str1 =  ' it is a beautifull day.'\n",
      "str1.split() then  ['it', 'is', 'a', 'beautifull', 'day.']\n",
      "str1.capitalize() =   it is a beautifull day.\n",
      "str1.find(\"a\") =  7\n",
      "str1.index(\"a\") =  7\n",
      "str1.endswith(\"ay\") =  False\n",
      "str1.startswith(\"it\") =  False\n",
      "str1.title() =   It Is A Beautifull Day.\n",
      "str1.upper() =   IT IS A BEAUTIFULL DAY.\n",
      "str1.lower() =   it is a beautifull day.\n",
      "str1.lstrip() =  it is a beautifull day.\n",
      "str1.rstrip() =   it is a beautifull day\n",
      "str1.strip() =  it is a beautifull day.\n",
      "str1.replace(\"beautifull\",\"bad\") =   it is a bad day.\n",
      "\",\".join(str1.split()) =  it,is,a,beautifull,day.\n",
      "len(str1) =  24\n"
     ]
    }
   ],
   "source": [
    "str1 = ' it is a beautifull day.'\n",
    "\n",
    "print('str1 = ', repr(str1))\n",
    "print('str1.split() then ', str1.split())\n",
    "print('str1.capitalize() = ', str1.capitalize())\n",
    "print('str1.find(\"a\") = ', str1.find(\"a\")) #找不到返回-1\n",
    "print('str1.index(\"a\") = ', str1.index(\"a\")) #找不到抛出异常\n",
    "print('str1.endswith(\"ay\") = ', str1.endswith(\"ay\"))\n",
    "print('str1.startswith(\"it\") = ', str1.startswith(\"it\"))\n",
    "print('str1.title() = ', str1.title())\n",
    "print('str1.upper() = ', str1.upper())\n",
    "print('str1.lower() = ', str1.lower())\n",
    "print('str1.lstrip() = ', str1.lstrip())\n",
    "print('str1.rstrip() = ', str1.rstrip('.'))\n",
    "print('str1.strip() = ', str1.strip())\n",
    "print('str1.replace(\"beautifull\",\"bad\") = ', str1.replace(\"beautifull\", \"bad\"))\n",
    "print('\",\".join(str1.split()) = ', \",\".join(str1.split()))\n",
    "print('len(str1) = ' ,len(str1))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "?str1.capitalize"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. 字符串格式化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "it is a beautifull day.\n",
      "Julia. Your age is 18\n",
      "Hello, Julia\n",
      "It's a bad day.\n",
      "Let's go home.\n",
      "      Name       Age\n",
      "--------------------\n",
      "     Julia      1.23\n"
     ]
    }
   ],
   "source": [
    "print('it is a %s day.' % 'beautifull')\n",
    "print('%s. Your age is %d' % ('Julia', 18))\n",
    "print('''Hello, %s\n",
    "It's a %s day.\n",
    "Let's go %s.''' % ('Julia', 'bad', 'home'))\n",
    "\n",
    "print('%10s%10s' % ('Name', 'Age'))\n",
    "print('-' * 20)\n",
    "print('%10s%10.2f' % ('Julia', 1.23456))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. 使用正则表达式\n",
    "正则表达式(regular expression)描述了一种字符串匹配的模式（pattern），可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "|表示法|描述|正则表达式示例|可匹配字符串|不可匹配字符串|\n",
    "|---|---|---|---|---|\n",
    "|.|匹配任意一个字符|a.a|aaa或aba|aab|\n",
    "|^|匹配字符串开始位置|^aa|aaa|baa|\n",
    "|\\$|匹配字符串结束位置|aa\\$|aaa|aab|\n",
    "|\\*|匹配0次或多次前面出现的正则表达式|a\\*b|b或ab或aab|cb|\n",
    "|+|匹配1次或多次前面出现的正则表达式|a+b|ab或aab|b|\n",
    "|?|匹配0次或1次前面出现的正则表达式|a?b|b或ab|aab|\n",
    "|{N}|匹配N次前面出现的正则表达式|a{2}b|aab|ab|\n",
    "|{N,M}|匹配N至M次前面出现的正则表达式|a{1,2}b|ab或aab|aaab|\n",
    "|\\d|匹配一个数字|data\\d|data0或data1|dataa|\n",
    "|\\w|匹配一个字母或数字|data\\w|data0或dataa|data-\n",
    "|\\s|匹配一个空格|data\\sdata|data data|datadata|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wi\n",
      "163\n",
      "['wise@163.com;', 'soe@qq.com']\n",
      "['wise@163.com', 'soe@qq.com']\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "s = 'wise@163.com; soe@qq.com'\n",
    "m1 = re.match('\\w{2}', s) #从字符串开始位置进行匹配\n",
    "if m1 is not None:\n",
    "    print(m1.group())\n",
    "    \n",
    "m2 = re.search('\\d+', s)\n",
    "if m2 is not None:\n",
    "    print(m2.group()) \n",
    "\n",
    "g1 = s.split()\n",
    "print(g1)\n",
    "    \n",
    "g2 = re.split('[\\s;]+', s)\n",
    "\n",
    "print(g2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('wise', '163', 'com')\n"
     ]
    }
   ],
   "source": [
    "m3 = re.search('(\\w+)@(\\d+)\\.(\\w+)', s)\n",
    "if m3 is not None:\n",
    "    print(m3.groups())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('wise', '163', 'com')\n"
     ]
    }
   ],
   "source": [
    "m3 = re.search('(\\w+)@(.+?)\\.(\\w+)', s) # * + ?等默认采用贪婪匹配，后面加上？采用非贪婪匹配\n",
    "if m3 is not None:\n",
    "    print(m3.groups())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('wise', '163', 'com'), ('soe', 'qq', 'com')]\n"
     ]
    }
   ],
   "source": [
    "s = 'wise@163.com; soe@qq.com'\n",
    "g3 = re.findall('(\\w+)@(.+?)\\.(\\w+)', s) # * + ?等默认采用贪婪匹配，后面加上？采用非贪婪匹配\n",
    "print(g3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'python@163.com; python@qq.com'"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.sub('(wise|soe)', 'python', s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('wise', '163', 'com')\n",
      "('soe', 'qq', 'com')\n"
     ]
    }
   ],
   "source": [
    "r = re.compile('(\\w+)@(\\w+)\\.(\\w+)')\n",
    "for g in g2:\n",
    "    m = r.search(g)\n",
    "    if m is not None:\n",
    "        print(m.groups()) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. 练习：从字符串中去掉不需要的字符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Hello   world \n",
      "!===\n"
     ]
    }
   ],
   "source": [
    "s = '--- Hello   world \\n!==='\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Hello world !'"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.sub('[\\s\\n]+', ' ',s.lstrip('-').rstrip('=').strip())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 四、函数和类\n",
    "在计算机世界我们随处可以见的一种方法，那就是抽象。冯诺依曼提出了计算机的基本结构，这是对计算机硬件的一次抽象。而对0和1的抽象构建了整个计算机软件的基石。函数和类也是如此，通过函数和类抽象，我们得以不去关心底层的实现，直接在更高的层次上思考和解决问题。不再重复制造轮子，得以站在前人的肩膀上。\n",
    "![](images/hammer.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Mike\n",
      "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n"
     ]
    }
   ],
   "source": [
    "def say_hello(x):\n",
    "    print('Hello, ' + x)\n",
    "\n",
    "def get_fabs(num):\n",
    "    f = [0,1]\n",
    "    while num > 2:\n",
    "        f.append(f[-1] + f[-2])\n",
    "        num -= 1\n",
    "    return f\n",
    "\n",
    "say_hello('Mike')\n",
    "f = get_fabs(10)\n",
    "print(f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 函数的参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "1\n",
      "2\n",
      "3\n",
      "--------------------\n",
      "1 2 3\n",
      "1 2 3\n",
      "--------------------\n",
      "1 2\n",
      "(3, 4, 5)\n",
      "1 2\n",
      "{'c': 3, 'd': 4, 'e': 5}\n",
      "--------------------\n",
      "(1, 2)\n",
      "{'c': 3, 'd': 4, 'e': 5}\n"
     ]
    }
   ],
   "source": [
    "def foo(*params): # 接受位置参数，自动打包\n",
    "    for i in params:\n",
    "        print(i)\n",
    "\n",
    "\n",
    "def bar(**kwparams): # 接受关键字参数，自动打包\n",
    "    for i in kwparams:\n",
    "        print(kwparams[i])\n",
    "\n",
    "def bar2(a=0,b=1):\n",
    "    print(a,b)\n",
    "\n",
    "foo(1,2,3,4)\n",
    "bar(a=1,b=2,c=3)\n",
    "\n",
    "print('-' * 20)\n",
    "\n",
    "def foo2(a,b,c):\n",
    "    print(a,b,c)\n",
    "\n",
    "def bar2(a=1,b=2,c=3): # 设置参数默认值\n",
    "    print(a,b,c)\n",
    "\n",
    "p1 = (1,2,3)\n",
    "p2 = {'a':1,'b':2,'c':3}\n",
    "\n",
    "foo2(*p1) # 自动解包\n",
    "bar2(**p2) #自动解包\n",
    "\n",
    "print('-' * 20)\n",
    "\n",
    "def foo3(a,b,*params):\n",
    "    print(a,b)\n",
    "    print(params)\n",
    "\n",
    "def bar3(a,b,**kwparams):\n",
    "    print(a,b)\n",
    "    print(kwparams)\n",
    "\n",
    "foo3(1,2,3,4,5)\n",
    "bar3(1,2,c=3,d=4,e=5)\n",
    "\n",
    "print('-' * 20)\n",
    "\n",
    "def foo4(*params,**kwparams):\n",
    "    print(params)\n",
    "    print(kwparams)\n",
    "\n",
    "foo4(1,2,c=3,d=4,e=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. lambda表达式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lambda_add = lambda x, y: x + y\n",
    "def lambda_add(x,y):\n",
    "    return x + y\n",
    "\n",
    "lambda_add(1, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 递归函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1024\n",
      "3628800\n",
      "34\n"
     ]
    }
   ],
   "source": [
    "def get_pow(x, n):\n",
    "    if n == 0:\n",
    "        return 1\n",
    "    else:\n",
    "        return x * get_pow(x, n-1)\n",
    "\n",
    "\n",
    "print(get_pow(2,10))\n",
    "\n",
    "\n",
    "def get_fact(n):\n",
    "    if n == 1:\n",
    "        return 1\n",
    "    else:\n",
    "        return n * get_fact(n-1)\n",
    "\n",
    "print(get_fact(10))\n",
    "\n",
    "\n",
    "def get_fabs(n):\n",
    "    if n == 1:\n",
    "        return 0\n",
    "    elif n == 2:\n",
    "        return 1\n",
    "    else:\n",
    "        return get_fabs(n-1) + get_fabs(n-2)\n",
    "\n",
    "print(get_fabs(10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 类\n",
    "类是一种数据结构，类是现实世界的抽象。对象和实例是类的具体化。可以类比一下，类是蓝图或者模型，用来产生真实的物体(实例)。因此使用关键字class就有类别，种属这样的意义。类是面向对象编程的基础，通过类结构定义实现面向对象的特性：封装、继承和多态。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lucky is here\n",
      "Lucky says hello\n",
      "Lucky runs to park\n",
      "Super is here\n",
      "Super says hi\n",
      "Super makes oxygen\n",
      "Super thinks the world\n",
      "--------------------\n",
      "Lucky is here\n",
      "Lucky says ok\n",
      "Super is here\n",
      "Super says ok\n"
     ]
    }
   ],
   "source": [
    "class Plant(object):\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "        print(self.name, \"is here\")\n",
    "\n",
    "    def make_oxygen(self):\n",
    "        print(self.name,'makes oxygen')\n",
    "\n",
    "\n",
    "class Animal(object):\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "        print(self.name, 'is here')\n",
    "\n",
    "    def say(self, something):\n",
    "        print(self.name , 'says', something)\n",
    "\n",
    "\n",
    "class Dog(Animal): # 继承\n",
    "    def __init__(self, name):\n",
    "        self.name = name     \n",
    "        super(Dog, self).__init__(name)\n",
    "\n",
    "    def run(self, somewhere):\n",
    "        print(self.name, 'runs to', somewhere)\n",
    "\n",
    "\n",
    "class PlantFish(Plant, Animal):   # 多重继承 \n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "        super(PlantFish, self).__init__(name)\n",
    "    \n",
    "    def think(self, something):\n",
    "        print(self.name, 'thinks', something)\n",
    "\n",
    "dog = Dog(\"Lucky\")\n",
    "dog.say('hello')\n",
    "dog.run('park')\n",
    "\n",
    "plant_fish = PlantFish(\"Super\")\n",
    "plant_fish.say('hi')\n",
    "plant_fish.make_oxygen()\n",
    "plant_fish.think('the world')\n",
    "\n",
    "print('-' * 20)\n",
    "\n",
    "def make_sound(obj): # 多态\n",
    "    obj.say('ok')\n",
    "\n",
    "make_sound(Dog('Lucky'))\n",
    "make_sound(PlantFish('Super'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 五、模块和包\n",
    "模块间相互独立相互引用是任何一种编程语言的基础能力。对于“模块”这个词在各种编程语言中或许是不同的，但我们可以简单认为一个程序文件是一个模块，文件里包含了类或者方法的定义。每种编程语言对于模块和包管理都有一定的约定，不了解这些约定，那会给学习这种语言的带来障碍。下面梳理一下Python的这些约定。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. python搜索路径\n",
    "运行python应用或引用python模块，python解释器要有一个查找的过程。可以通过设置一个环境变量PYTHONPATH为python增加一个搜索路径，以方便查找到相关python模块（不同的操作系统环境变量的设置稍有不同，默认以下都是WIndows环境），这与众多应用程序需要设置一个系统环境变量的道理是一样的。在命令行中可以通过以下命令设置："
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "set PYTHONPATH=path/to/your/modules/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "进入python环境后可以，通过python的sys.path属性获得当前搜索路径的配置，可以看到之前我们设置的路径已经在当前搜索路径中了。也可以通过sys模块的append方法临时在python环境中增加搜索路径。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\python36.zip',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\DLLs',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\Sphinx-1.5.1-py3.6.egg',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32\\\\lib',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\Pythonwin',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\setuptools-27.2.0-py3.6.egg',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\IPython\\\\extensions',\n",
       " 'C:\\\\Users\\\\Administrator\\\\.ipython']"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "sys.path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\python36.zip',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\DLLs',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\Sphinx-1.5.1-py3.6.egg',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32\\\\lib',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\Pythonwin',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\setuptools-27.2.0-py3.6.egg',\n",
       " 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\IPython\\\\extensions',\n",
       " 'C:\\\\Users\\\\Administrator\\\\.ipython',\n",
       " 'e:\\\\Project\\\\Python\\\\course-begining-python\\\\moduleandpackage']"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "os.getcwd() \n",
    "sys.path.append(os.path.join(os.getcwd(), 'moduleandpackage'))\n",
    "sys.path"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. python中的模块和包\n",
    "每个.py文件都是可以认为是一个python模块，.py文件中可以包含类、方法、变量和常量（python还没有严格意义上的常量，只是约定大写的变量作为常量），文件内也可以直接写所有的逻辑语句并在加载时从上之下直接执行，这与其他解释型语言是类似的。例如我们选择在文件夹moduleandpackage中创建一个文本文件person.py文件即创建了一个简单的python模块，其内容如下："
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# person.py\n",
    "ID = 1\n",
    "name = 'This person'\n",
    "print(name)\n",
    "def say(something):\n",
    "    print(name,'says', something)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "那么接下来我们就可以在python环境中执行person.py。我们可以直接像执行一个批处理文件那样执行person.py。本质上任何一个python应用的入口模块都是这样被执行的（像C#和Java中的main函数），但是引用一个模块，就要建立运行它的上下文环境。我们之前设置了一个搜索路径，以便python解释器找到person.py模块，然后import person模块，即可访问其中的方法或变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This person\n",
      "__init__\n",
      "This pet\n",
      "This person says hello\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'This person'"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import person\n",
    "person.say('hello')\n",
    "person.name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "python需要去某些固定的路径下去查找python模块，上面我们设置在moduleandpackage中查找。但是这些路径下也是有目录层次的，特别是引用第三方包时，我们也需要知道一定的层次关系。实际上，python通过目录和文件构建包结构，并且包是层层嵌套的，和目录层层嵌套是一样的，这样就构成了包内的访问路径（或者命名空间，也可以说python包的命名空间与其目录和文件结构是对应了，似乎缺少了一些灵活，但也更简单）。例如我们在moduleandpackage文件夹下，创建一个文件夹animal，里面创建一个文本文件pet.py，其内容如下："
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# pet.py\n",
    "ID = 2\n",
    "name =  \"This pet\"\n",
    "print name\n",
    "def run(somewhere):\n",
    "    print name,'runs', somewhere"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "按照Python的约定，需要在animal文件夹中创建名为\\_\\_init\\_\\_.py的空文本文件，以标识animal文件夹是一个包。倘若animal文件夹内还有文件夹作为包，也必须包含\\_\\_init\\_\\_.py文件。这样就层层标识了访问的路径。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This pet\n",
      "This pet runs everywhere\n"
     ]
    }
   ],
   "source": [
    "import animal.pet\n",
    "print(animal.pet.name)\n",
    "animal.pet.run(\"everywhere\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "或者使用from关键字直接导入模块内的属性或方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This pet\n",
      "This pet runs everywhere\n"
     ]
    }
   ],
   "source": [
    "from animal.pet import name,run\n",
    "print(name)\n",
    "run(\"everywhere\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. python模块间引用\n",
    "简答来说，只要python模块在其执行环境配置的搜索路径中，并且其所在位置是包结构的一部分，那么我们就可以引用该模块。上文已经提供了模块引用的基本示例。只不过模块间引用时import语句是写在模块文件中，我们修改person.py模块的代码。\n",
    "#### from、import和as\n",
    "import语句可以写在文档中的任何位置，甚至if语句中，以便更好的控制模块引用。还可以通过as语句，使用另一个变量名进行引用，以避免变量名冲突。"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# person.py\n",
    "ID = 1\n",
    "name =  \"This person\"\n",
    "print name\n",
    "\n",
    "def say(something):\n",
    "    print name,'says', something\n",
    "\n",
    "from animal.pet import name as pet_name, run as pet_run\n",
    "\n",
    "def have():\n",
    "    print name,'has', pet_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This person\n",
      "This pet\n",
      "This person has This pet\n"
     ]
    }
   ],
   "source": [
    "import person\n",
    "print(person.name)\n",
    "print(person.pet_name)\n",
    "person.have()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### \\*通配符"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "from animal.pet import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但这样有可能造成变量名冲突，如下name变量发生冲突，覆盖了person自己的name变量的值。但如果想用\\*通配符，又不想引用模块中的所有变量，可以在模块中用变量\\_\\_all\\_\\_进行限制，修改pet.py，限制只引用ID和run两个变量名。"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# pet.py\n",
    "__all__ = ['ID','run']\n",
    "\n",
    "ID = 2\n",
    "name =  \"This pet\"\n",
    "print name\n",
    "\n",
    "def run(somewhere):\n",
    "    print name,'runs', somewhere"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 引用包\n",
    "上面都是引用具体的animal.pet模块，但是这对于一个相对独立且拥有众多的模块的包来说就显得麻烦了，可以直接import animal，但是python不像C#引用dll或者java引用jar那样，引用后包内的模块就可以通过命名空间直接访问了（在访问控制许可下）。默认情况下python还是需要导入包内的具体模块的，但有个变通的办法，就是使用包中\\_\\_init\\_\\_.py文件，提前准备包内需要被引用的各个模块中的变量，类似于向外部引用者暴露包内接口。\\_\\_init\\_\\_.py文件代码是在包或者包内模块被引用时执行的，因而可以在其中做一些初始化的工作。修改animal文件夹中\\_\\_init\\_\\_.py文件如下，其中模块可以使用绝对路径和相对路径，相对路径中一个句点.代表同级目录，两个句点..代表父目录。"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# __init__.py\n",
    "print \"__init__\"\n",
    "from pet import name as pet_name, run as pet_run"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "修改person.py，直接引用anmial包："
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# person.py\n",
    "\n",
    "ID = 1\n",
    "name =  \"This person\"\n",
    "print name\n",
    "\n",
    "def say(something):\n",
    "    print name,'says', something\n",
    "\n",
    "import animal\n",
    "\n",
    "def have():\n",
    "    print name,'has', pet_name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在python环境中引用person模块，person引用animal，并自动执行\\_\\_init\\_\\_的代码加载相关变量，通过dir方法可以查看模块中的变量，其中两个下划线开始的变量每个模块都有，这些变量具有特殊的作用，是python预定义的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['ID',\n",
       " '__builtins__',\n",
       " '__cached__',\n",
       " '__doc__',\n",
       " '__file__',\n",
       " '__loader__',\n",
       " '__name__',\n",
       " '__package__',\n",
       " '__spec__',\n",
       " 'have',\n",
       " 'name',\n",
       " 'pet',\n",
       " 'pet_name',\n",
       " 'pet_run',\n",
       " 'say']"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import person\n",
    "dir(person)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 六、练习"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 八皇后问题\n",
    "任何两个皇后都不能在同一行，同一列或同一斜线上。\n",
    "![](http://img.blog.csdn.net/20130902004602187)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 3, 0, 2), (2, 0, 3, 1)]\n"
     ]
    }
   ],
   "source": [
    "def queens(num=8,state=()):\n",
    "    for pos in range(num):\n",
    "        if not confilict(state, pos):\n",
    "            if len(state) == num - 1:\n",
    "                yield (pos,)\n",
    "            else:\n",
    "                for result in queens(num, state + (pos,)):\n",
    "                    yield (pos,) + result\n",
    "\n",
    "\n",
    "def confilict(state, x):\n",
    "    y = len(state)\n",
    "    for i in range(y):\n",
    "        if abs(state[i]-x) in (0, y-i):\n",
    "            return True\n",
    "    return False\n",
    "\n",
    "\n",
    "print(list(queens(4)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
